package com.cmc.cloud.cmclink.doc.service.impl.multimodaltransport;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiValidEnum;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoVslvoyDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoMapper;
import com.cmc.cloud.cmclink.doc.mapper.BlnoVslvoyMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.CustomerRpcService;
import com.cmc.cloud.cmclink.doc.service.multimodaltransport.MultiBlnoOpService;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoPageRespVO;
import com.cmc.cloud.cmclink.doc.vo.multimodaltransport.multiblnoop.MultiBlnoOpReqVO;
import com.cmc.cloud.cmclink.doc.vo.multimodaltransport.multiblnoop.MultiBlnoUpdateVO;
import com.cmc.cloud.cmclink.doc.vo.multimodaltransport.multiblnoop.MultiBlnoVelVoyVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.ex.Assertion;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cmes.framework.security.core.util.SecurityFrameworkUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lzp
 * @date 2025/10/23 14:48
 * @description
 */
@Service
@Slf4j
public class MultiBlnoOpServiceImpl implements MultiBlnoOpService {

    @Autowired
    private BlnoMapper blnoMapper;

    @Resource
    private CustomerRpcService customerRpcService;

    @Resource
    private BlnoVslvoyMapper blnoVslvoyMapper;

    private static final String TBA = "TBA";

    @Override
    public PageResult<BlnoPageRespVO> getMultiBlnoPage(MultiBlnoOpReqVO multiBlnoOpReqVo) {
        IPage<BlnoPageRespVO> page = Page.of(multiBlnoOpReqVo.getPageNo(), multiBlnoOpReqVo.getPageSize());
        IPage<BlnoPageRespVO> pageResult = blnoMapper.getMultiBlnoBaseInfo(page, multiBlnoOpReqVo);
        List<BlnoPageRespVO> voList = BeanUtil.copyToList(pageResult.getRecords(), BlnoPageRespVO.class);
        if (CollectionUtil.isNotEmpty(voList)) {
            customerRpcService.fillName(voList);
        }
        return new PageResult<>(voList, pageResult.getTotal());
    }

    @Override
    public List<MultiBlnoVelVoyVO> getMultiBlnoVslVoyInfo(List<Long> blnoIds) {
        List<Integer> route = Arrays.asList(1, 2);
        if (CollectionUtil.isEmpty(blnoIds)) {
            return Collections.emptyList();
        }
        //校验提单是否已经锁定，如果已经锁定报错
        LambdaQueryWrapperX<BlnoDO> blnoDoLambdaQueryWrapper = new LambdaQueryWrapperX<>();
        blnoDoLambdaQueryWrapper.in(BlnoDO::getId, blnoIds)
                .eq(BlnoDO::getBlLockFlag, true)
                .eq(BlnoDO::getValid, SiValidEnum.VALID.getValue());
        List<BlnoDO> blnoDoList = blnoMapper.selectList(blnoDoLambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(blnoDoList)) {
            List<String> blnos = blnoDoList.stream().map(BlnoDO::getBlNo).collect(Collectors.toList());
            Assertion.assertTrue(false).raise0(BlnoErrorCodeConstants.BLNO_IS_LOCK.getCode(), String.join(",", blnos));
        }
        Set<String> stringSet = new HashSet<>(4);
        List<MultiBlnoVelVoyVO> multiBlnoVelVoyVoList = new ArrayList<>(16);
        LambdaQueryWrapperX<BlnoVslvoyDO> lambdaQueryWrapperx = new LambdaQueryWrapperX<>();
        lambdaQueryWrapperx.inIfPresent(BlnoVslvoyDO::getBlnoId, blnoIds);
        List<BlnoVslvoyDO> blnoVslvoyDoList = blnoVslvoyMapper.selectList(lambdaQueryWrapperx);
        if (CollectionUtil.isEmpty(blnoVslvoyDoList)) {
            return Collections.emptyList();
        }
        Map<Long, List<BlnoVslvoyDO>> listMap = blnoVslvoyDoList.stream().filter(item -> route.contains(item.getRouteNo())).collect(Collectors.groupingBy(BlnoVslvoyDO::getBlnoId));
        for (Map.Entry<Long, List<BlnoVslvoyDO>> entry : listMap.entrySet()) {
            List<BlnoVslvoyDO> blnoVslvoyDos = entry.getValue();
            MultiBlnoVelVoyVO multiBlnoVelVoyVo = new MultiBlnoVelVoyVO();
            multiBlnoVelVoyVo.setBlnoId(entry.getKey());
            blnoVslvoyDos.forEach(item -> {
                if (item.getRouteNo() == 1) {
                    multiBlnoVelVoyVo.setPreVesselCode(item.getVesselCode());
                    multiBlnoVelVoyVo.setPreVoyage(item.getVoyageEx());
                    multiBlnoVelVoyVo.setPrePodCode(item.getPodCode());
                    multiBlnoVelVoyVo.setVslVoyId(item.getId());
                    stringSet.add(StringUtils.isEmpty(item.getVesselCode()) ? TBA : item.getVesselCode() + (StringUtils.isEmpty(item.getVoyageEx()) ? TBA : item.getVoyageEx()));
                    if (stringSet.size() > 1) {
                        Assertion.assertNotEmpty(String.valueOf(item.getBlnoId())).raise0(BlnoErrorCodeConstants.BLNO_VSLVOY.getCode(), item.getVesselCode(), item.getVoyageEx());
                    }
                }
                if (item.getRouteNo() == 2) {
                    multiBlnoVelVoyVo.setVoyage(item.getVoyageEx());
                    multiBlnoVelVoyVo.setVesselCode(item.getVesselCode());
                }
            });

            multiBlnoVelVoyVoList.add(multiBlnoVelVoyVo);
        }
        return multiBlnoVelVoyVoList;
    }

    @Override
    public void updateBlnoVslVoyInfo(MultiBlnoUpdateVO multiBlnoUpdateVo) {
        LambdaQueryWrapperX<BlnoVslvoyDO> lambdaQueryWrapper = new LambdaQueryWrapperX<>();
        lambdaQueryWrapper.in(BlnoVslvoyDO::getId, multiBlnoUpdateVo.getVslVoyIds());
        List<BlnoVslvoyDO> blnoVslvoyDoList = blnoVslvoyMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(blnoVslvoyDoList)) {
            return;
        }
        blnoVslvoyDoList.forEach(item -> {
            item.setVoyageEx(multiBlnoUpdateVo.getPreVoyage());
            item.setVesselCode(multiBlnoUpdateVo.getPreVesselCode());
            item.setVoyageIm(multiBlnoUpdateVo.getVoyage());
            item.setUpdater(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
            item.setUpdateTime(LocalDateTime.now());
        });
        blnoVslvoyMapper.updateBatch(blnoVslvoyDoList);
    }
}
